bitkeeper revision 1.1527.2.1 (429368a2F0SR4yrzuHsrRucuwriYqA)
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Tue, 24 May 2005 17:47:14 +0000 (17:47 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Tue, 24 May 2005 17:47:14 +0000 (17:47 +0000)
Implement the parts of vm save which need interaction with xend
as part of xend, instead of using xfrd.
Execute xc_linux_save in a seperate process so that it can't
crash xend.  Also handle errors passed from xc_linux_save.
xen_domain.c:
  Disable save in xfrd.
xc_save.c:
  new file
Makefile:
  Add xc_save.
XendDomainInfo.py:
  Add suspended state and threading Condition with notification, allowing
  easy waiting for state changes.
XendDomain.py:
  Implement the parts of vm save which need interaction with xend
  as part of xend, instead of using xfrd.  Set state to "suspended"
  when detecting a suspended domain.
  Fix reading output from subprocesses.
  Fix ValueError in xen_domain().
xc.c:
  Remove python binding for xc_linux_save.
xc_linux_save.c:
  Implement the parts of vm save which need interaction with xend
  as part of xend, instead of using xfrd.  Also run xc_linux_save
  in a seperate process.
xc_linux_restore.c:
  Flush output so that xend picks it up timely.
  Also disable debug output again.
xc.h:
  Update xc_linux_save prototype and fix comments for xc_linux_{save,restore}.
ignore:
  Add tools/xcutils/xc_save.
xpopen.py:
  Exit with 127 if exec fails.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
12 files changed:
.rootkeys
BitKeeper/etc/ignore
tools/libxc/xc.h
tools/libxc/xc_linux_restore.c
tools/libxc/xc_linux_save.c
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/util/xpopen.py
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/xcutils/Makefile
tools/xcutils/xc_save.c [new file with mode: 0644]
tools/xfrd/xen_domain.c

index f1618d901cb18d46f41815d7bd1140cd5a8f83a9..26b7f664a77eca76a0451fae1841290866c8d6a3 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 41d58ba6ijEF6fedqRO5vFu7uCirZg tools/xcs/xcsdump.c
 4292540couq-V0TPwyQ6bspNEWNcvw tools/xcutils/Makefile
 42925407VysDb9O06OK_RUzTZxfLoA tools/xcutils/xc_restore.c
+42936745WTLYamYsmXm_JGJ72JX-_Q tools/xcutils/xc_save.c
 403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
 40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
 420d52d2_znVbT4JAPIU36vQOme83g tools/xentrace/xenctx.c
index a48ab6cff972a269d405e5cbb4e72549db71f326..d996d45a72308694393a03a0ef3ee4ef90533b8f 100644 (file)
@@ -127,6 +127,7 @@ tools/x2d2/minixend
 tools/xcs/xcs
 tools/xcs/xcsdump
 tools/xcutils/xc_restore
+tools/xcutils/xc_save
 tools/xentrace/xentrace
 tools/xfrd/xfrd
 xen/BLOG
index 3c7f7e5564dfa48862333a6e5685b4d850c71044..c31222fc90275b0093a09f8ef2d9c0f4a52043fa 100644 (file)
@@ -225,23 +225,22 @@ int xc_shadow_control(int xc_handle,
 struct XcIOContext;
 
 /**
- * This function will save a domain running Linux to an IO context.  This
- * IO context is currently a private interface making this function difficult
- * to call.  It's interface will likely change in the future.
+ * This function will save a domain running Linux.
  *
  * @parm xc_handle a handle to an open hypervisor interface
- * @parm ioctxt the IO context to save a domain to
+ * @parm fd the file descriptor to save a domain to
+ * @parm dom the id of the domain
  * @return 0 on success, -1 on failure
  */
-int xc_linux_save(int xc_handle, struct XcIOContext *ioctxt);
+int xc_linux_save(int xc_handle, int fd, u32 dom);
 
 /**
- * This function will restore a saved domain running Linux to an IO context.
- * Like xc_linux_save(), this function uses a parameter who's structure is
- * privately defined.  It's interface will also likely change.
+ * This function will restore a saved domain running Linux.
  *
  * @parm xc_handle a handle to an open hypervisor interface
- * @parm ioctxt the IO context to restore a domain from
+ * @parm fd the file descriptor to restore a domain from
+ * @parm dom the id of the domain
+ * @parm nr_pfns the number of pages
  * @return 0 on success, -1 on failure
  */
 int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns);
index c679e9dd5a2e7379d4ddcea11eed667faed79563..cc8e4b4d290a1654cb185ccb159904126a4d0829 100644 (file)
 
 #define MAX_BATCH_SIZE 1024
 
-#define DEBUG 01
+#define DEBUG 0
 
 #if 1
-#define ERR(_f, _a...) fprintf ( stderr, _f , ## _a )
+#define ERR(_f, _a...) fprintf ( stderr, _f , ## _a ); fflush(stderr)
 #else
 #define ERR(_f, _a...) ((void)0)
 #endif
 
 #if DEBUG
-#define DPRINTF(_f, _a...) fprintf ( stdout, _f , ## _a )
+#define DPRINTF(_f, _a...) fprintf ( stdout, _f , ## _a ); fflush(stdout)
 #else
 #define DPRINTF(_f, _a...) ((void)0)
 #endif
 
 #define PROGRESS 0
 #if PROGRESS
-#define PPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a )
+#define PPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a ); fflush(stderr)
 #else
 #define PPRINTF(_f, _a...)
 #endif
index 8273f9c56c62cc93ab313ed8b80e72c733c151d3..feb051884d107837508c0b9039402d77d6886dc7 100644 (file)
 
 #define MAX_MBIT_RATE 500
 
-#define DEBUG  0
-#define DDEBUG 0
+#define DEBUG 0
+
+#if 1
+#define ERR(_f, _a...) fprintf ( stderr, _f , ## _a )
+#else
+#define ERR(_f, _a...) ((void)0)
+#endif
 
 #if DEBUG
-#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#define DPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a )
 #else
 #define DPRINTF(_f, _a...) ((void)0)
 #endif
 
-#if DDEBUG
-#define DDPRINTF(_f, _a...) printf ( _f , ## _a )
+#define PROGRESS 0
+#if PROGRESS
+#define PPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a )
 #else
-#define DDPRINTF(_f, _a...) ((void)0)
+#define PPRINTF(_f, _a...)
 #endif
 
 /*
@@ -144,7 +150,7 @@ static long long tv_delta( struct timeval *new, struct timeval *old )
 }
 
 
-#define START_MBIT_RATE ioctxt->resource
+#define START_MBIT_RATE 0 //ioctxt->resource
 
 static int mbit_rate, ombit_rate = 0;
 static int burst_time_us = -1;
@@ -167,7 +173,8 @@ static int burst_time_us = -1;
 #define RATE_TO_BTU 781250
 #define BURST_TIME_US burst_time_us
 
-static int xcio_ratewrite(XcIOContext *ioctxt, void *buf, int n)
+static int
+ratewrite(int io_fd, void *buf, int n)
 {
     static int budget = 0;
     static struct timeval last_put = { 0 };
@@ -176,16 +183,15 @@ static int xcio_ratewrite(XcIOContext *ioctxt, void *buf, int n)
     long long delta;
 
     if (START_MBIT_RATE == 0)
-       return xcio_write(ioctxt, buf, n);
+       return write(io_fd, buf, n);
     
     budget -= n;
     if (budget < 0) {
        if (MBIT_RATE != ombit_rate) {
            BURST_TIME_US = RATE_TO_BTU / MBIT_RATE;
            ombit_rate = MBIT_RATE;
-           xcio_info(ioctxt,
-                     "rate limit: %d mbit/s burst budget %d slot time %d\n",
-                     MBIT_RATE, BURST_BUDGET, BURST_TIME_US);
+           DPRINTF("rate limit: %d mbit/s burst budget %d slot time %d\n",
+                   MBIT_RATE, BURST_BUDGET, BURST_TIME_US);
        }
        if (last_put.tv_sec == 0) {
            budget += BURST_BUDGET;
@@ -213,7 +219,7 @@ static int xcio_ratewrite(XcIOContext *ioctxt, void *buf, int n)
            }
        }
     }
-    return xcio_write(ioctxt, buf, n);
+    return write(io_fd, buf, n);
 }
 
 static int print_stats( int xc_handle, u32 domid, 
@@ -235,7 +241,7 @@ static int print_stats( int xc_handle, u32 domid,
     d1_cpu_now = xc_domain_get_cpu_usage(xc_handle, domid, /* FIXME */ 0)/1000;
 
     if ( (d0_cpu_now == -1) || (d1_cpu_now == -1) ) 
-        printf("ARRHHH!!\n");
+        fprintf(stderr, "ARRHHH!!\n");
 
     wall_delta = tv_delta(&wall_now,&wall_last)/1000;
 
@@ -245,14 +251,15 @@ static int print_stats( int xc_handle, u32 domid,
     d1_cpu_delta  = (d1_cpu_now - d1_cpu_last)/1000;
 
     if ( print )
-        printf("delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, "
-               "dirtied %dMb/s %" PRId32 " pages\n",
-               wall_delta, 
-               (int)((d0_cpu_delta*100)/wall_delta),
-               (int)((d1_cpu_delta*100)/wall_delta),
-               (int)((pages_sent*PAGE_SIZE)/(wall_delta*(1000/8))),
-               (int)((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8))),
-               stats->dirty_count);
+        fprintf(stderr,
+               "delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, "
+               "dirtied %dMb/s %" PRId32 " pages\n",
+               wall_delta, 
+               (int)((d0_cpu_delta*100)/wall_delta),
+               (int)((d1_cpu_delta*100)/wall_delta),
+               (int)((pages_sent*PAGE_SIZE)/(wall_delta*(1000/8))),
+               (int)((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8))),
+               stats->dirty_count);
 
     if (((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8))) > mbit_rate) {
        mbit_rate = (int)((stats->dirty_count*PAGE_SIZE)/(wall_delta*(1000/8)))
@@ -268,24 +275,6 @@ static int print_stats( int xc_handle, u32 domid,
     return 0;
 }
 
-/** Write the vmconfig string.
- * It is stored as a 4-byte count 'n' followed by n bytes.
- *
- * @param ioctxt i/o context
- * @return 0 on success, non-zero on error.
- */
-static int write_vmconfig(XcIOContext *ioctxt)
-{
-    int err = -1;
-    if(xcio_write(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))) 
-        goto exit;
-    if(xcio_write(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)) 
-        goto exit;
-    err = 0;
-  exit:
-    return err;
-}
-
 static int analysis_phase( int xc_handle, u32 domid, 
                            int nr_pfns, unsigned long *arr, int runs )
 {
@@ -302,7 +291,7 @@ static int analysis_phase( int xc_handle, u32 domid,
         xc_shadow_control( xc_handle, domid, 
                            DOM0_SHADOW_CONTROL_OP_CLEAN,
                            arr, nr_pfns, NULL);
-        printf("#Flush\n");
+        fprintf(stderr, "#Flush\n");
         for ( i = 0; i < 40; i++ )
         {     
             usleep(50000);     
@@ -311,11 +300,11 @@ static int analysis_phase( int xc_handle, u32 domid,
                                DOM0_SHADOW_CONTROL_OP_PEEK,
                                NULL, 0, &stats);
 
-            printf("now= %lld faults= %" PRId32 " dirty= %" PRId32
-                   " dirty_net= %" PRId32 " dirty_block= %" PRId32"\n", 
-                   ((now-start)+500)/1000, 
-                   stats.fault_count, stats.dirty_count,
-                   stats.dirty_net_count, stats.dirty_block_count);
+            fprintf(stderr, "now= %lld faults= %" PRId32 " dirty= %" PRId32
+                   " dirty_net= %" PRId32 " dirty_block= %" PRId32"\n", 
+                   ((now-start)+500)/1000, 
+                   stats.fault_count, stats.dirty_count,
+                   stats.dirty_net_count, stats.dirty_block_count);
         }
     }
 
@@ -323,26 +312,36 @@ static int analysis_phase( int xc_handle, u32 domid,
 }
 
 
-int suspend_and_state(int xc_handle, XcIOContext *ioctxt,                    
+int suspend_and_state(int xc_handle, int io_fd,        int dom,              
                       xc_dominfo_t *info,
                       vcpu_guest_context_t *ctxt)
 {
     int i=0;
-    
-    xcio_suspend_domain(ioctxt);
+    char ans[30];
+
+    printf("suspend\n");
+    fflush(stdout);
+    if (fgets(ans, sizeof(ans), stdin) == NULL) {
+       ERR("failed reading suspend reply");
+       return -1;
+    }
+    if (strncmp(ans, "done\n", 5)) {
+       ERR("suspend reply incorrect: %s", ans);
+       return -1;
+    }
 
 retry:
 
-    if ( xc_domain_getinfo(xc_handle, ioctxt->domain, 1, info) != 1)
+    if ( xc_domain_getinfo(xc_handle, dom, 1, info) != 1)
     {
-       xcio_error(ioctxt, "Could not get domain info");
+       ERR("Could not get domain info");
        return -1;
     }
 
-    if ( xc_domain_get_vcpu_context(xc_handle, ioctxt->domain, 0 /* XXX */, 
+    if ( xc_domain_get_vcpu_context(xc_handle, dom, 0 /* XXX */, 
                                    ctxt) )
     {
-        xcio_error(ioctxt, "Could not get vcpu context");
+        ERR("Could not get vcpu context");
     }
 
     if ( info->shutdown && info->shutdown_reason == SHUTDOWN_suspend )
@@ -353,9 +352,9 @@ retry:
     if ( info->paused )
     {
        // try unpausing domain, wait, and retest       
-       xc_domain_unpause( xc_handle, ioctxt->domain );
+       xc_domain_unpause( xc_handle, dom );
 
-       xcio_error(ioctxt, "Domain was paused. Wait and re-test.");
+       ERR("Domain was paused. Wait and re-test.");
        usleep(10000);  // 10ms
 
        goto retry;
@@ -364,25 +363,24 @@ retry:
 
     if( ++i < 100 )
     {
-       xcio_error(ioctxt, "Retry suspend domain.");
+       ERR("Retry suspend domain.");
        usleep(10000);  // 10ms 
        goto retry;
     }
 
-    xcio_error(ioctxt, "Unable to suspend domain.");
+    ERR("Unable to suspend domain.");
 
     return -1;
 }
 
-int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
+int xc_linux_save(int xc_handle, int io_fd, u32 dom)
 {
     xc_dominfo_t info;
 
     int rc = 1, i, j, k, last_iter, iter = 0;
     unsigned long mfn;
-    u32 domid = ioctxt->domain;
-    int live =  (ioctxt->flags & XCFLAGS_LIVE);
-    int debug = (ioctxt->flags & XCFLAGS_DEBUG);
+    int live =  0; // (ioctxt->flags & XCFLAGS_LIVE);
+    int debug = 0; // (ioctxt->flags & XCFLAGS_DEBUG);
     int sent_last_iter, skip_this_iter;
 
     /* Important tuning parameters */
@@ -440,29 +438,29 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
 
     MBIT_RATE = START_MBIT_RATE;
 
-    xcio_info(ioctxt, "xc_linux_save start %d\n", domid);
+    DPRINTF("xc_linux_save start %d\n", dom);
     
     if (mlock(&ctxt, sizeof(ctxt))) {
-        xcio_perror(ioctxt, "Unable to mlock ctxt");
+        ERR("Unable to mlock ctxt");
         return 1;
     }
     
-    if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1)
+    if ( xc_domain_getinfo(xc_handle, dom, 1, &info) != 1)
     {
-        xcio_error(ioctxt, "Could not get domain info");
+        ERR("Could not get domain info");
         goto out;
     }
-    if ( xc_domain_get_vcpu_context( xc_handle, domid, /* FIXME */ 0, 
+    if ( xc_domain_get_vcpu_context( xc_handle, dom, /* FIXME */ 0, 
                                 &ctxt) )
     {
-        xcio_error(ioctxt, "Could not get vcpu context");
+        ERR("Could not get vcpu context");
         goto out;
     }
     shared_info_frame = info.shared_info_frame;
 
     /* A cheesy test to see whether the domain contains valid state. */
     if ( ctxt.pt_base == 0 ){
-        xcio_error(ioctxt, "Domain is not in a valid Linux guest OS state");
+        ERR("Domain is not in a valid Linux guest OS state");
         goto out;
     }
     
@@ -470,31 +468,29 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
 
     /* cheesy sanity check */
     if ( nr_pfns > 1024*1024 ){
-        xcio_error(ioctxt, 
-                   "Invalid state record -- pfn count out of range: %lu", 
-                   nr_pfns);
+        ERR("Invalid state record -- pfn count out of range: %lu", nr_pfns);
         goto out;
     }
 
 
     /* Map the shared info frame */
-    live_shinfo = xc_map_foreign_range(xc_handle, domid,
+    live_shinfo = xc_map_foreign_range(xc_handle, dom,
                                         PAGE_SIZE, PROT_READ,
                                         shared_info_frame);
 
     if (!live_shinfo){
-        xcio_error(ioctxt, "Couldn't map live_shinfo");
+        ERR("Couldn't map live_shinfo");
         goto out;
     }
 
     /* the pfn_to_mfn_frame_list fits in a single page */
     live_pfn_to_mfn_frame_list = 
-        xc_map_foreign_range(xc_handle, domid
+        xc_map_foreign_range(xc_handle, dom, 
                               PAGE_SIZE, PROT_READ, 
                               live_shinfo->arch.pfn_to_mfn_frame_list );
 
     if (!live_pfn_to_mfn_frame_list){
-        xcio_error(ioctxt, "Couldn't map pfn_to_mfn_frame_list");
+        ERR("Couldn't map pfn_to_mfn_frame_list");
         goto out;
     }
 
@@ -504,12 +500,12 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
        (its not clear why it would want to change them, and we'll be OK
        from a safety POV anyhow. */
 
-    live_pfn_to_mfn_table = xc_map_foreign_batch(xc_handle, domid
+    live_pfn_to_mfn_table = xc_map_foreign_batch(xc_handle, dom, 
                                                  PROT_READ,
                                                  live_pfn_to_mfn_frame_list,
                                                  (nr_pfns+1023)/1024 );  
     if( !live_pfn_to_mfn_table ){
-        xcio_perror(ioctxt, "Couldn't map pfn_to_mfn table");
+        ERR("Couldn't map pfn_to_mfn table");
         goto out;
     }
 
@@ -526,8 +522,7 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
 
     for ( i = 0; i < nr_pfns; i += 1024 ){
         if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ){
-            xcio_error(ioctxt, 
-                       "Frame# in pfn-to-mfn frame list is not in pseudophys");
+            ERR("Frame# in pfn-to-mfn frame list is not in pseudophys");
             goto out;
         }
     }
@@ -537,10 +532,10 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
 
     if( live )
     {
-        if ( xc_shadow_control( xc_handle, domid
+        if ( xc_shadow_control( xc_handle, dom, 
                                 DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY,
                                 NULL, 0, NULL ) < 0 ) {
-            xcio_error(ioctxt, "Couldn't enable shadow mode");
+            ERR("Couldn't enable shadow mode");
             goto out;
         }
 
@@ -551,9 +546,9 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
 
         last_iter = 1;
 
-       if ( suspend_and_state( xc_handle, ioctxt, &info, &ctxt) )
+       if ( suspend_and_state( xc_handle, io_fd, dom, &info, &ctxt) )
        {
-           xcio_error(ioctxt, "Domain appears not to have suspended");
+           ERR("Domain appears not to have suspended");
            goto out;
        }
 
@@ -577,27 +572,27 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
         to_skip = malloc( sz );
 
         if (!to_send || !to_fix || !to_skip){
-            xcio_error(ioctxt, "Couldn't allocate to_send array");
+            ERR("Couldn't allocate to_send array");
             goto out;
         }
 
         memset( to_send, 0xff, sz );
 
         if ( mlock( to_send, sz ) ){
-            xcio_perror(ioctxt, "Unable to mlock to_send");
+            ERR("Unable to mlock to_send");
             return 1;
         }
 
         /* (to fix is local only) */
 
         if ( mlock( to_skip, sz ) ){
-            xcio_perror(ioctxt, "Unable to mlock to_skip");
+            ERR("Unable to mlock to_skip");
             return 1;
         }
 
     }
 
-    analysis_phase( xc_handle, domid, nr_pfns, to_skip, 0 );
+    analysis_phase( xc_handle, dom, nr_pfns, to_skip, 0 );
 
     /* We want zeroed memory so use calloc rather than malloc. */
     pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long));
@@ -609,7 +604,7 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
     }
 
     if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ){
-        xcio_error(ioctxt, "Unable to mlock");
+        ERR("Unable to mlock");
         goto out;
     }
 
@@ -626,33 +621,29 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
            
            if( (live_mfn_to_pfn_table[mfn] != i) && (mfn != 0xffffffffUL) )
            {
-               printf("i=0x%x mfn=%lx live_mfn_to_pfn_table=%lx\n",
-                      i,mfn,live_mfn_to_pfn_table[mfn]);
+               fprintf(stderr, "i=0x%x mfn=%lx live_mfn_to_pfn_table=%lx\n",
+                       i,mfn,live_mfn_to_pfn_table[mfn]);
                err++;
            }
        }
-       printf("Had %d unexplained entries in p2m table\n",err);
+       fprintf(stderr, "Had %d unexplained entries in p2m table\n",err);
     }
 #endif
 
 
     /* Start writing out the saved-domain record. */
 
-    if ( xcio_write(ioctxt, "LinuxGuestRecord",    16) ){
-        xcio_error(ioctxt, "Error writing header");
-        goto out;
-    }
-    if(write_vmconfig(ioctxt)){
-        xcio_error(ioctxt, "Error writing vmconfig");
-        goto out;
+    if (write(io_fd, &nr_pfns, sizeof(unsigned long)) !=
+       sizeof(unsigned long)) {
+       ERR("write: nr_pfns");
+       goto out;
     }
-    if ( xcio_write(ioctxt, &nr_pfns,              sizeof(unsigned long)) ||
-         xcio_write(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ){
-        xcio_error(ioctxt, "Error writing header");
+    if (write(io_fd, pfn_to_mfn_frame_list, PAGE_SIZE) != PAGE_SIZE) {
+        ERR("write: pfn_to_mfn_frame_list");
         goto out;
     }
 
-    print_stats( xc_handle, domid, 0, &stats, 0 );
+    print_stats( xc_handle, dom, 0, &stats, 0 );
 
     /* Now write out each data page, canonicalising page tables as we go... */
     
@@ -665,13 +656,13 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
         prev_pc = 0;
         N=0;
 
-        xcio_info(ioctxt, "Saving memory pages: iter %d   0%%", iter);
+        DPRINTF("Saving memory pages: iter %d   0%%", iter);
 
         while( N < nr_pfns ){
             unsigned int this_pc = (N * 100) / nr_pfns;
 
             if ( (this_pc - prev_pc) >= 5 ){
-                xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc);
+                DPRINTF("\b\b\b\b%3d%%", this_pc);
                 prev_pc = this_pc;
             }
 
@@ -679,11 +670,11 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
                but this is fast enough for the moment. */
 
             if ( !last_iter && 
-                xc_shadow_control(xc_handle, domid
+                xc_shadow_control(xc_handle, dom, 
                                    DOM0_SHADOW_CONTROL_OP_PEEK,
                                    to_skip, nr_pfns, NULL) != nr_pfns )
            {
-                xcio_error(ioctxt, "Error peeking shadow bitmap");
+                ERR("Error peeking shadow bitmap");
                 goto out;
             }
      
@@ -733,8 +724,8 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
 
                     set_bit( n, to_fix );
                     if( iter>1 )
-                        DDPRINTF("netbuf race: iter %d, pfn %x. mfn %lx\n",
-                                 iter,n,pfn_type[batch]);
+                        DPRINTF("netbuf race: iter %d, pfn %x. mfn %lx\n",
+                               iter,n,pfn_type[batch]);
                     continue;
                 }
 
@@ -752,27 +743,27 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
                 batch++;
             }
      
-//            DDPRINTF("batch %d:%d (n=%d)\n", iter, batch, n);
+//            DPRINTF("batch %d:%d (n=%d)\n", iter, batch, n);
 
             if ( batch == 0 )
                 goto skip; /* vanishingly unlikely... */
       
-            if ( (region_base = xc_map_foreign_batch(xc_handle, domid
+            if ( (region_base = xc_map_foreign_batch(xc_handle, dom, 
                                                      PROT_READ,
                                                      pfn_type,
                                                      batch)) == 0 ){
-                xcio_perror(ioctxt, "map batch failed");
+                ERR("map batch failed");
                 goto out;
             }
      
-            if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) ){
-                xcio_error(ioctxt, "get_pfn_type_batch failed");
+            if ( get_pfn_type_batch(xc_handle, dom, batch, pfn_type) ){
+                ERR("get_pfn_type_batch failed");
                 goto out;
             }
      
             for ( j = 0; j < batch; j++ ){
                 if ( (pfn_type[j] & LTAB_MASK) == XTAB ){
-                    DDPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
+                    DPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
                     continue;
                 }
   
@@ -789,13 +780,14 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
                 pfn_type[j] = (pfn_type[j] & LTAB_MASK) | pfn_batch[j];
             }
 
-            if ( xcio_write(ioctxt, &batch, sizeof(int) ) ){
-                xcio_error(ioctxt, "Error when writing to state file (2)");
+            if (write(io_fd, &batch, sizeof(int)) != sizeof(int)) {
+                ERR("Error when writing to state file (2)");
                 goto out;
             }
 
-            if ( xcio_write(ioctxt, pfn_type, sizeof(unsigned long)*j ) ){
-                xcio_error(ioctxt, "Error when writing to state file (3)");
+            if (write(io_fd, pfn_type, sizeof(unsigned long)*j) !=
+               sizeof(unsigned long)*j) {
+                ERR("Error when writing to state file (3)");
                 goto out;
             }
      
@@ -803,7 +795,7 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
             for( j = 0; j < batch; j++ ){
                 /* write out pages in batch */
                 if( (pfn_type[j] & LTAB_MASK) == XTAB){
-                    DDPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]);
+                    DPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]);
                     continue;
                 }
   
@@ -827,14 +819,14 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
                         if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
                         {
                             /* I don't think this should ever happen */
-                            printf("FNI %d : [%08lx,%d] pte=%08lx, "
-                                   "mfn=%08lx, pfn=%08lx [mfn]=%08lx\n",
-                                   j, pfn_type[j], k,
-                                   page[k], mfn, live_mfn_to_pfn_table[mfn],
-                                   (live_mfn_to_pfn_table[mfn]<nr_pfns)? 
-                                   live_pfn_to_mfn_table[
-                                       live_mfn_to_pfn_table[mfn]] : 
-                                   0xdeadbeef);
+                            fprintf(stderr, "FNI %d : [%08lx,%d] pte=%08lx, "
+                                   "mfn=%08lx, pfn=%08lx [mfn]=%08lx\n",
+                                   j, pfn_type[j], k,
+                                   page[k], mfn, live_mfn_to_pfn_table[mfn],
+                                   (live_mfn_to_pfn_table[mfn]<nr_pfns)? 
+                                   live_pfn_to_mfn_table[
+                                       live_mfn_to_pfn_table[mfn]] : 
+                                   0xdeadbeef);
 
                             pfn = 0; /* be suspicious */
                         }
@@ -843,26 +835,25 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
                         page[k] |= pfn << PAGE_SHIFT;
    
 #if 0
-                        printf("L%d i=%d pfn=%d mfn=%d k=%d pte=%08lx "
-                               "xpfn=%d\n",
-                               pfn_type[j]>>28,
-                               j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT);
+                        fprintf(stderr,
+                               "L%d i=%d pfn=%d mfn=%d k=%d pte=%08lx "
+                               "xpfn=%d\n",
+                               pfn_type[j]>>28,
+                               j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT);
 #endif     
-   
+                       
                     } /* end of page table rewrite for loop */
       
-                    if ( xcio_ratewrite(ioctxt, page, PAGE_SIZE) ){
-                        xcio_error(ioctxt, 
-                                   "Error when writing to state file (4)");
+                    if (ratewrite(io_fd, page, PAGE_SIZE) != PAGE_SIZE) {
+                        ERR("Error when writing to state file (4)");
                         goto out;
                     }
       
                 }  /* end of it's a PT page */ else {  /* normal page */
 
-                    if ( xcio_ratewrite(ioctxt, region_base + (PAGE_SIZE*j), 
-                                     PAGE_SIZE) ){
-                        xcio_error(ioctxt, 
-                                   "Error when writing to state file (5)");
+                    if (ratewrite(io_fd, region_base + (PAGE_SIZE*j), 
+                                 PAGE_SIZE) != PAGE_SIZE) {
+                        ERR("Error when writing to state file (5)");
                         goto out;
                     }
                 }
@@ -878,27 +869,26 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
 
         total_sent += sent_this_iter;
 
-        xcio_info(ioctxt, "\r %d: sent %d, skipped %d, ", 
+        DPRINTF("\r %d: sent %d, skipped %d, ", 
                        iter, sent_this_iter, skip_this_iter );
 
         if ( last_iter ) {
-            print_stats( xc_handle, domid, sent_this_iter, &stats, 1);
+            print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
 
-            xcio_info(ioctxt, "Total pages sent= %d (%.2fx)\n", 
+            DPRINTF("Total pages sent= %d (%.2fx)\n", 
                            total_sent, ((float)total_sent)/nr_pfns );
-            xcio_info(ioctxt, "(of which %d were fixups)\n", needed_to_fix  );
+            DPRINTF("(of which %d were fixups)\n", needed_to_fix  );
         }       
 
         if (last_iter && debug){
             int minusone = -1;
             memset( to_send, 0xff, (nr_pfns+8)/8 );
             debug = 0;
-            printf("Entering debug resend-all mode\n");
+            fprintf(stderr, "Entering debug resend-all mode\n");
     
             /* send "-1" to put receiver into debug mode */
-            if ( xcio_write(ioctxt, &minusone, sizeof(int)) )
-            {
-                xcio_error(ioctxt, "Error when writing to state file (6)");
+            if (write(io_fd, &minusone, sizeof(int)) != sizeof(int)) {
+                ERR("Error when writing to state file (6)");
                 goto out;
             }
 
@@ -919,30 +909,28 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
                 DPRINTF("Start last iteration\n");
                 last_iter = 1;
 
-               if ( suspend_and_state( xc_handle, ioctxt, &info, &ctxt) )
+               if ( suspend_and_state( xc_handle, io_fd, dom, &info, &ctxt) )
                {
-                   xcio_error(ioctxt, 
-                               "Domain appears not to have suspended");
+                   ERR("Domain appears not to have suspended");
                    goto out;
                }
 
-               xcio_info(ioctxt,
-                          "SUSPEND shinfo %08lx eip %08u esi %08u\n",
-                          info.shared_info_frame,
-                          ctxt.user_regs.eip, ctxt.user_regs.esi );
+               DPRINTF("SUSPEND shinfo %08lx eip %08u esi %08u\n",
+                       info.shared_info_frame,
+                       ctxt.user_regs.eip, ctxt.user_regs.esi);
             } 
 
-            if ( xc_shadow_control( xc_handle, domid
+            if ( xc_shadow_control( xc_handle, dom, 
                                     DOM0_SHADOW_CONTROL_OP_CLEAN,
                                     to_send, nr_pfns, &stats ) != nr_pfns ) 
             {
-                xcio_error(ioctxt, "Error flushing shadow PT");
+                ERR("Error flushing shadow PT");
                 goto out;
             }
 
             sent_last_iter = sent_this_iter;
 
-            print_stats( xc_handle, domid, sent_this_iter, &stats, 1);
+            print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
      
         }
 
@@ -955,9 +943,8 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
     rc = 0;
     
     /* Zero terminate */
-    if ( xcio_write(ioctxt, &rc, sizeof(int)) )
-    {
-        xcio_error(ioctxt, "Error when writing to state file (6)");
+    if (write(io_fd, &rc, sizeof(int)) != sizeof(int)) {
+        ERR("Error when writing to state file (6)");
         goto out;
     }
 
@@ -972,9 +959,8 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
                j++;
        }
 
-       if ( xcio_write(ioctxt, &j, sizeof(unsigned int)) )
-       {
-           xcio_error(ioctxt, "Error when writing to state file (6a)");
+       if (write(io_fd, &j, sizeof(unsigned int)) != sizeof(unsigned int)) {
+           ERR("Error when writing to state file (6a)");
            goto out;
        }       
 
@@ -987,10 +973,9 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
            i++;
            if ( j == 1024 || i == nr_pfns )
            {
-               if ( xcio_write(ioctxt, &pfntab, sizeof(unsigned long)*j) )
-               {
-                   xcio_error(ioctxt, 
-                               "Error when writing to state file (6b)");
+               if (write(io_fd, &pfntab, sizeof(unsigned long)*j) !=
+                   sizeof(unsigned long)*j) {
+                   ERR("Error when writing to state file (6b)");
                    goto out;
                }       
                j = 0;
@@ -999,47 +984,47 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
     }
 
     /* Map the suspend-record MFN to pin it. The page must be owned by 
-       domid for this to succeed. */
-    p_srec = xc_map_foreign_range(xc_handle, domid,
+       dom for this to succeed. */
+    p_srec = xc_map_foreign_range(xc_handle, dom,
                                    sizeof(*p_srec), PROT_READ, 
                                    ctxt.user_regs.esi);
     if (!p_srec){
-        xcio_error(ioctxt, "Couldn't map suspend record");
+        ERR("Couldn't map suspend record");
         goto out;
     }
 
     if (nr_pfns != p_srec->nr_pfns )
     {
-       xcio_error(ioctxt, "Suspend record nr_pfns unexpected (%ld != %ld)",
+       ERR("Suspend record nr_pfns unexpected (%ld != %ld)",
                   p_srec->nr_pfns, nr_pfns);
         goto out;
     }
 
     /* Canonicalise the suspend-record frame number. */
     if ( !translate_mfn_to_pfn(&ctxt.user_regs.esi) ){
-        xcio_error(ioctxt, "Suspend record is not in range of pseudophys map");
+        ERR("Suspend record is not in range of pseudophys map");
         goto out;
     }
 
     /* Canonicalise each GDT frame number. */
     for ( i = 0; i < ctxt.gdt_ents; i += 512 ) {
         if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) {
-            xcio_error(ioctxt, "GDT frame is not in range of pseudophys map");
+            ERR("GDT frame is not in range of pseudophys map");
             goto out;
         }
     }
 
     /* Canonicalise the page table base pointer. */
     if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) ) {
-        xcio_error(ioctxt, "PT base is not in range of pseudophys map");
+        ERR("PT base is not in range of pseudophys map");
         goto out;
     }
     ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] <<
         PAGE_SHIFT;
 
-    if ( xcio_write(ioctxt, &ctxt,       sizeof(ctxt)) ||
-         xcio_write(ioctxt, live_shinfo, PAGE_SIZE) ) {
-        xcio_error(ioctxt, "Error when writing to state file (1)");
+    if (write(io_fd, &ctxt, sizeof(ctxt)) != sizeof(ctxt) ||
+       write(io_fd, live_shinfo, PAGE_SIZE) != PAGE_SIZE) {
+        ERR("Error when writing to state file (1)");
         goto out;
     }
 
index 8132ff1047d8dfaa99f75c412209a6b6b3808079..653d7c01d166c4e804934d2910d94d47f3191774 100644 (file)
@@ -254,93 +254,6 @@ static PyObject *pyxc_domain_getinfo(PyObject *self,
     return list;
 }
 
-static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file)
-{
-    int rc = -1;
-    int fd = -1;
-    int open_flags = (O_CREAT | O_EXCL | O_WRONLY);
-    int open_mode = 0644;
-
-    printf("%s>\n", __FUNCTION__);
-
-    if ( (fd = open(state_file, open_flags, open_mode)) < 0 )
-    {
-        xcio_perror(ctxt, "Could not open file for writing");
-        goto exit;
-    }
-
-    printf("%s>gzip_stream_fdopen... \n", __FUNCTION__);
-
-    /* Compression rate 1: we want speed over compression. 
-     * We're mainly going for those zero pages, after all.
-     */
-    ctxt->io = gzip_stream_fdopen(fd, "wb1");
-    if ( ctxt->io == NULL )
-    {
-        xcio_perror(ctxt, "Could not allocate compression state");
-        goto exit;
-    }
-
-    printf("%s> xc_linux_save...\n", __FUNCTION__);
-
-    rc = xc_linux_save(xc->xc_handle, ctxt);
-
-  exit:
-    if ( ctxt->io != NULL )
-        IOStream_close(ctxt->io);
-    if ( fd >= 0 )
-        close(fd);
-    unlink(state_file);
-    printf("%s> rc=%d\n", __FUNCTION__, rc);
-    return rc;
-}
-
-static PyObject *pyxc_linux_save(PyObject *self,
-                                 PyObject *args,
-                                 PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    char *state_file;
-    int progress = 1, debug = 0;
-    PyObject *val = NULL;
-    int rc = -1;
-    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
-
-    static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list, 
-                                      &ioctxt.domain,
-                                      &state_file,
-                                      &ioctxt.vmconfig,
-                                      &progress, 
-                                      &debug) )
-        goto exit;
-
-    ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0);
-
-    if ( progress )
-        ioctxt.flags |= XCFLAGS_VERBOSE;
-    if ( debug )
-        ioctxt.flags |= XCFLAGS_DEBUG;
-
-    if ( (state_file == NULL) || (state_file[0] == '\0') )
-        goto exit;
-    
-    rc = file_save(xc, &ioctxt, state_file);
-    if ( rc != 0 )
-    {
-        PyErr_SetFromErrno(xc_error);
-        goto exit;
-    } 
-
-    Py_INCREF(zero);
-    val = zero;
-
-  exit:
-    return val;
-}
-
 static PyObject *pyxc_linux_build(PyObject *self,
                                   PyObject *args,
                                   PyObject *kwds)
@@ -999,15 +912,6 @@ static PyMethodDef pyxc_methods[] = {
       "reason why it shut itself down.\n" 
       " vcpu_to_cpu [[int]]: List that maps VCPUS to CPUS\n" },
 
-    { "linux_save", 
-      (PyCFunction)pyxc_linux_save, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Save the CPU and memory state of a Linux guest OS.\n"
-      " dom        [int]:    Identifier of domain to be saved.\n"
-      " state_file [str]:    Name of state file. Must not currently exist.\n"
-      " progress   [int, 1]: Bool - display a running progress indication?\n\n"
-      "Returns: [int] 0 on success; -1 on error.\n" },
-
     { "linux_build", 
       (PyCFunction)pyxc_linux_build, 
       METH_VARARGS | METH_KEYWORDS, "\n"
index 78bbefdd2c8d62c49ce6c4124aaceb74656d3a51..b0c880fafe34be140e45fb9f856419ecd73e06a1 100644 (file)
@@ -129,7 +129,7 @@ class xPopen3:
         try:
             os.execvp(cmd[0], cmd)
         finally:
-            os._exit(1)
+            os._exit(127)
 
     def poll(self):
         """Return the exit status of the child process if it has finished,
index 2320e8758d6081dbd27dd590eb0552fd76fe99b0..2ee81c761cc6197584e517f9efbe83b4b3dbaa74 100644 (file)
@@ -90,7 +90,10 @@ class XendDomain:
         """Get info about a single domain from xc.
         Returns None if not found.
         """
-        dom = int(dom)
+        try:
+            dom = int(dom)
+        except ValueError:
+            return None
         dominfo = xc.domain_getinfo(dom, 1)
         if dominfo == [] or dominfo[0]['dom'] != dom:
             dominfo = None
@@ -198,6 +201,8 @@ class XendDomain:
                         log.debug('XendDomain>reap> Suspended domain died id=%s', id)
                     else:
                         eserver.inject('xend.domain.suspended', [name, id])
+                        if dominfo:
+                            dominfo.state_set("suspended")
                         continue
                 if reason in ['poweroff', 'reboot']:
                     eserver.inject('xend.domain.exit', [name, id, reason])
@@ -349,7 +354,7 @@ class XendDomain:
 
             l = fd.read_exact(sizeof_int,
                               "not a valid guest state file: config size read")
-            vmconfig_size = unpack("i", l)[0] # XXX endianess
+            vmconfig_size = unpack("!i", l)[0]
             vmconfig_buf = fd.read_exact(vmconfig_size,
                 "not a valid guest state file: config read")
 
@@ -384,17 +389,22 @@ class XendDomain:
             p.register(child.childerr.fileno())
             while True:
                 r = p.poll()
-                for l in child.childerr.readlines():
-                    log.error(l.rstrip())
-                    lasterr = l.rstrip()
-                for l in child.fromchild.readlines():
-                    log.info(l.rstrip())
+                for (fd, event) in r:
+                    if not event & select.POLLIN:
+                        continue
+                    if fd == child.childerr.fileno():
+                        l = child.childerr.readline()
+                        log.error(l.rstrip())
+                        lasterr = l.rstrip()
+                    if fd == child.fromchild.fileno():
+                        l = child.fromchild.readline()
+                        log.info(l.rstrip())
                 if filter(lambda (fd, event): event & select.POLLHUP, r):
                     break
 
             if child.wait() != 0:
                 raise XendError("xc_restore failed: %s" % lasterr)
-            
+
             return dominfo
 
         except IOError, ex:
@@ -592,10 +602,66 @@ class XendDomain:
         @param dst:      destination file
         @param progress: output progress if true
         """
-        dominfo = self.domain_lookup(id)
-        xmigrate = XendMigrate.instance()
-        return xmigrate.save_begin(dominfo, dst)
-    
+
+        SIGNATURE = "LinuxGuestRecord"
+        sizeof_int = calcsize("i")
+        PATH_XC_SAVE = "/usr/libexec/xen/xc_save"
+
+        try:
+            dominfo = self.domain_lookup(id)
+
+            fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
+
+            if os.write(fd, SIGNATURE) != len(SIGNATURE):
+                raise XendError("could not write guest state file: signature")
+
+            config = sxp.to_string(dominfo.sxpr())
+            if os.write(fd, pack("!i", len(config))) != sizeof_int:
+                raise XendError("could not write guest state file: config len")
+            if os.write(fd, config) != len(config):
+                raise XendError("could not write guest state file: config")
+
+            cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd),
+                   dominfo.id]
+            log.info("[xc_save] " + join(cmd))
+            child = xPopen3(cmd, True, -1, [fd, xc.handle()])
+            
+            lasterr = ""
+            p = select.poll()
+            p.register(child.fromchild.fileno())
+            p.register(child.childerr.fileno())
+            while True:
+                r = p.poll()
+                for (fd, event) in r:
+                    if not event & select.POLLIN:
+                        continue
+                    if fd == child.childerr.fileno():
+                        l = child.childerr.readline()
+                        log.error(l.rstrip())
+                        lasterr = l.rstrip()
+                    if fd == child.fromchild.fileno():
+                        l = child.fromchild.readline()
+                        if l.rstrip() == "suspend":
+                            log.info("suspending %s" % dominfo.id)
+                            self.domain_shutdown(dominfo.id, reason='suspend')
+                            dominfo.state_wait("suspended")
+                            log.info("suspend %s done" % dominfo.id)
+                            child.tochild.write("done\n")
+                            child.tochild.flush()
+                if filter(lambda (fd, event): event & select.POLLHUP, r):
+                    break
+
+            if child.wait() >> 8 == 127:
+                lasterr = "popen %s failed" % PATH_XC_SAVE
+            if child.wait() != 0:
+                raise XendError("xc_save failed: %s" % lasterr)
+
+            self.domain_destroy(dominfo.id)
+            return None
+
+        except:
+            raise
+
     def domain_pincpu(self, id, vcpu, cpumap):
         """Set which cpus vcpu can use
 
index d7762fe9162dac00e828a705ce82aeff2ccea99b..8eba3a9aad098b03627fab06404b93af4e99a981 100644 (file)
@@ -11,6 +11,7 @@ Author: Mike Wray <mike.wray@hp.com>
 import string
 import os
 import time
+import threading
 
 import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
 import xen.util.ip
@@ -74,6 +75,7 @@ STATE_RESTART_BOOTING = 'booting'
 
 STATE_VM_OK         = "ok"
 STATE_VM_TERMINATED = "terminated"
+STATE_VM_SUSPENDED  = "suspended"
 
 
 def domain_exists(name):
@@ -288,6 +290,7 @@ class XendDomainInfo:
         self.netif_backend = False
         #todo: state: running, suspended
         self.state = STATE_VM_OK
+        self.state_updated = threading.Condition()
         self.shutdown_pending = None
 
         #todo: set to migrate info if migrating
@@ -328,6 +331,19 @@ class XendDomainInfo:
         self.info = info
         self.memory = self.info['mem_kb'] / 1024
 
+    def state_set(self, state):
+        self.state_updated.acquire()
+        if self.state != state:
+            self.state = state
+            self.state_updated.notifyAll()
+        self.state_updated.release()
+
+    def state_wait(self, state):
+        self.state_updated.acquire()
+        while self.state != state:
+            self.state_updated.wait()
+        self.state_updated.release()
+
     def __str__(self):
         s = "domain"
         s += " id=" + self.id
index 71c3c6a404afcb49909607c14a4ee6164573372f..613358df8b371aa136429d3969a8c41fa5fb987d 100644 (file)
@@ -28,9 +28,10 @@ CFLAGS += $(INCLUDES)
 CFLAGS += -Wp,-MD,.$(@F).d
 PROG_DEP = .*.d
 
-PROGRAMS               = xc_restore
+PROGRAMS               = xc_restore xc_save
 
 xc_restore_OBJS                = xc_restore.o
+xc_save_OBJS           = xc_save.o
 
 LDLIBS                 = -L$(XEN_LIBXC) -L$(XEN_LIBXUTIL) -lxc -lxutil
 
diff --git a/tools/xcutils/xc_save.c b/tools/xcutils/xc_save.c
new file mode 100644 (file)
index 0000000..6ca1d5c
--- /dev/null
@@ -0,0 +1,29 @@
+/* 
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2005 by Christian Limpach
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+
+#include <xc.h>
+
+int
+main(int argc, char **argv)
+{
+    unsigned int xc_fd, io_fd, domid;
+
+    if (argc != 4)
+       errx(1, "usage: %s xcfd iofd domid", argv[0]);
+
+    xc_fd = atoi(argv[1]);
+    io_fd = atoi(argv[2]);
+    domid = atoi(argv[3]);
+
+    return xc_linux_save(xc_fd, io_fd, domid);
+}
index fb2951555ac7538d42d138b2bc62873b308c6ff3..659bf39cd68500598ba35ee86a9223163c9a1cc4 100644 (file)
@@ -61,6 +61,7 @@ int xen_domain_snd(Conn *xend, IOStream *io,
                    char *vmconfig, int vmconfig_n,
                    int live, int resource){
     int err = 0;
+#if 0
     XcIOContext _ioctxt = {}, *ioctxt = &_ioctxt;
     ioctxt->domain = dom;
     ioctxt->io = io;
@@ -76,6 +77,7 @@ int xen_domain_snd(Conn *xend, IOStream *io,
     ioctxt->resource = resource;
     err = xc_linux_save(xcinit(), ioctxt);
     dprintf("< err=%d\n", err);
+#endif
     return err;
 }